﻿using GBT.Entity.GBT_Manage;
using GBT.Util;
using EFCore.Sharding;
using LinqKit;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using System.Linq.Expressions;
using System;
using GBT.Entity.Base_Manage;
using GBT.Entity.GBT_Base_Manage;
using GBT.Entity;
using System.Data;
using GBT.IBusiness.GBT_Report;

namespace GBT.Business.GBT_Report
{
    public class GBT_AmoebaReportBusiness : BaseBusiness<GBT_ServiceRequest>, IGBT_AmoebaReportBusiness, ITransientDependency
    {
        public GBT_AmoebaReportBusiness(IDbAccessor db)
            : base(db)
        {
        }

        #region 外部接口

        public async Task<PageResult<GBT_ServiceRequestDTO>> GET_AmoebaDetailReportAsync(PageInput<GBT_ServiceRequestConditionDTO> input)
        {
            var q = GetIQueryable();
            var where = LinqHelper.True<GBT_ServiceRequestDTO>();
            var search = input.Search;

            Expression<Func<GBT_ServiceRequest, GBT_Base_Account, Base_User, Base_User, GBT_ServiceRequestDTO>> select = (sr, ba, bu, cbu) => new GBT_ServiceRequestDTO
            {
                RequestDepartmentId = "",
                DeliveryDepartmentId = "",
                AccountName = ba.Name,
                ApprovalName = bu.UserName,
                ApprovalOpinion = "",
                CreatorName = cbu.UserName,
            };
            select = select.BuildExtendSelectExpre();

            var list = from sr in q.AsExpandable()
                       join ba in Db.GetIQueryable<GBT_Base_Account>() on sr.AccountId equals ba.Id
                       join bu in Db.GetIQueryable<Base_User>() on sr.Approver equals bu.Id into bu_temp
                       from bu in bu_temp.DefaultIfEmpty()
                       join cbu in Db.GetIQueryable<Base_User>() on sr.CreatorId equals cbu.Id into cbu_temp
                       from cbu in cbu_temp.DefaultIfEmpty()
                       select @select.Invoke(sr, ba, bu, cbu);

            //筛选
            if (!search.Condition.IsNullOrEmpty() && !search.Keyword.IsNullOrEmpty())
            {
                var newWhere = DynamicExpressionParser.ParseLambda<GBT_ServiceRequestDTO, bool>(
                    ParsingConfig.Default, false, $@"{search.Condition}.Contains(@0)", search.Keyword);
                where = where.And(newWhere);
            }

            where = where.And(t => t.State.Equals(4));
            var listNew = await list.Where(where).OrderBy(t => t.State).ThenByDescending(t => t.CreateTime).GetPageResultAsync(input);
            await SetProperty(listNew.Data);
            return listNew;
        }

        public async Task<List<GBT_ServiceRequestDTO>> GET_ExportAmoebaDetailReportAsync(PageInput<GBT_ServiceRequestConditionDTO> input)
        {
            var q = GetIQueryable();
            var where = LinqHelper.True<GBT_ServiceRequestDTO>();
            var search = input.Search;

            Expression<Func<GBT_ServiceRequest, GBT_Base_Account, Base_User, Base_User, GBT_ServiceRequestDTO>> select = (sr, ba, bu, cbu) => new GBT_ServiceRequestDTO
            {
                RequestDepartmentId = "",
                DeliveryDepartmentId = "",
                AccountName = ba.Name,
                ApprovalName = bu.UserName,
                ApprovalOpinion = "",
                CreatorName = cbu.UserName,
            };
            select = select.BuildExtendSelectExpre();

            var list = from sr in q.AsExpandable()
                       join ba in Db.GetIQueryable<GBT_Base_Account>() on sr.AccountId equals ba.Id
                       join bu in Db.GetIQueryable<Base_User>() on sr.Approver equals bu.Id into bu_temp
                       from bu in bu_temp.DefaultIfEmpty()
                       join cbu in Db.GetIQueryable<Base_User>() on sr.CreatorId equals cbu.Id into cbu_temp
                       from cbu in cbu_temp.DefaultIfEmpty()
                       select @select.Invoke(sr, ba, bu, cbu);

            //筛选
            if (!search.Condition.IsNullOrEmpty() && !search.Keyword.IsNullOrEmpty())
            {
                var newWhere = DynamicExpressionParser.ParseLambda<GBT_ServiceRequestDTO, bool>(
                    ParsingConfig.Default, false, $@"{search.Condition}.Contains(@0)", search.Keyword);
                where = where.And(newWhere);
            }

            where = where.And(t => t.State.Equals(4));
            var listNew = await list.Where(where).OrderBy(t => t.State).ThenByDescending(t => t.CreateTime).ToListAsync();
            await SetProperty(listNew);
            return listNew;
        }
        #endregion

        #region 私有成员
        /// <summary>
        /// 获取服务请求部门
        /// </summary>
        /// <param name="serviceRequestIds"></param>
        /// <returns></returns>
        private async Task<List<GBT_DepartmentIdsDTO>> GetServiceRequestDepartmentIds(List<string> serviceRequestIds)
        {
            var deptInfo = await (from d in Db.GetIQueryable<Base_Department>()
                                  select new Base_Department
                                  {
                                      Id = d.Id,
                                      Name = d.Name,
                                  }).ToListAsync();

            var departmentIds = await (from sru in Db.GetIQueryable<GBT_ServiceRequest>()
                                       where serviceRequestIds.Contains(sru.Id)
                                       select new GBT_DepartmentIdsDTO
                                       {
                                           resquestId = sru.Id,
                                           departmentIds = sru.RequestDepartmentId
                                       }).ToListAsync();

            departmentIds.ForEach(t =>
            {
                var dept = t.departmentIds.ToList<string>();
                List<string> deptName = new List<string>();
                dept.ForEach(str =>
                {
                    deptName.AddRange(deptInfo.Where(dept => dept.Id == str).Select(dept => dept.Name).ToList());
                });
                t.departmentNames = deptName.ToString<string>();
            });
            return departmentIds;
        }

        /// <summary>
        /// 获取提供服务部门
        /// </summary>
        /// <param name="serviceRequestIds"></param>
        /// <returns></returns>
        private async Task<List<GBT_DepartmentIdsDTO>> GetServiceDeliveryDepartmentIds(List<string> serviceRequestIds)
        {
            var deptInfo = await (from d in Db.GetIQueryable<Base_Department>()
                                  select new Base_Department
                                  {
                                      Id = d.Id,
                                      Name = d.Name,
                                  }).ToListAsync();

            var departmentIds = await (from sru in Db.GetIQueryable<GBT_ServiceRequest>()
                                       where serviceRequestIds.Contains(sru.Id)
                                       select new GBT_DepartmentIdsDTO
                                       {
                                           resquestId = sru.Id,
                                           departmentIds = sru.DeliveryDepartmentId
                                       }).ToListAsync();

            departmentIds.ForEach(t =>
            {
                var dept = t.departmentIds.ToList<string>();
                List<string> deptName = new List<string>();
                dept.ForEach(str =>
                {
                    deptName.AddRange(deptInfo.Where(dept => dept.Id == str).Select(dept => dept.Name).ToList());
                });
                t.departmentNames = deptName.ToString<string>();
            });
            return departmentIds;
        }

        /// <summary>
        /// 设置 请求服务人员列表，提供服务人员列表，服务项目列表，审批记录列表等属性
        /// </summary>
        /// <param name="serviceRequestList"></param>
        /// <returns></returns>
        private async Task SetProperty(List<GBT_ServiceRequestDTO> serviceRequestList)
        {
            List<string> serviceRequestIds = serviceRequestList.Select(x => x.Id).ToList();

            //服务请求部门
            var serviceRequestDepartments = await GetServiceRequestDepartmentIds(serviceRequestIds);

            //提供服务部门
            var serviceDeliveryDepartments = await GetServiceDeliveryDepartmentIds(serviceRequestIds);

            #region 审批信息
            Expression<Func<GBT_Approval, Base_User, GBT_ApprovalDTO>> selectApproval = (a, bu) => new GBT_ApprovalDTO
            {
                UserName = bu.UserName,
            };
            selectApproval.BuildExtendSelectExpre();

            var approvalList = await (from a in Db.GetIQueryable<GBT_Approval>().AsExpandable()
                                      join bu in Db.GetIQueryable<Base_User>() on a.UserId equals bu.Id
                                      where serviceRequestIds.Contains(a.ServiceRequestId)
                                      select selectApproval.Invoke(a, bu)).ToListAsync();
            #endregion

            #region 返回结果
            serviceRequestList.ForEach(serviceRequest =>
            {
                serviceRequest.RequestDepartmentId = serviceRequestDepartments.Where(x => x.resquestId == serviceRequest.Id).Select(t => t.departmentIds).FirstOrDefault();
                serviceRequest.RequestDepartmentName = serviceRequestDepartments.Where(x => x.resquestId == serviceRequest.Id).Select(t => t.departmentNames).FirstOrDefault();
                serviceRequest.DeliveryDepartmentId = serviceDeliveryDepartments.Where(x => x.resquestId == serviceRequest.Id).Select(t => t.departmentIds).FirstOrDefault();
                serviceRequest.DeliveryDepartmentName = serviceDeliveryDepartments.Where(x => x.resquestId == serviceRequest.Id).Select(t => t.departmentNames).FirstOrDefault();
                var approvals = approvalList.Where(x => x.ServiceRequestId == serviceRequest.Id);
                serviceRequest.Approvals = approvals.ToList();
                var currentApproval = approvals.OrderByDescending(x => x.Id).FirstOrDefault();
                serviceRequest.CurrentApproval = currentApproval;
            });
            #endregion
        }
        #endregion
    }
}
